package modelo;

import java.util.List;
import java.util.ArrayList;

import excepciones.CantidadDePosicionesIncorrectasExcepcion;

public abstract class Barco {
	private int tamanio;
	private GeneradorDeMovimientos timon;
	protected List<Parte> partes;
	protected List<Posicion> posiciones;
	
	protected void crearBarco(List<Posicion> listaDePosiciones, Direccion unaDireccion, int unTamanio) throws CantidadDePosicionesIncorrectasExcepcion {
		if (listaDePosiciones.size() != unTamanio) {
			throw new CantidadDePosicionesIncorrectasExcepcion("ERROR: La cantidad de posiciones no es correcta.");
		}
		
		tamanio = unTamanio;
		posiciones = listaDePosiciones;
		timon = new GeneradorDeMovimientos(unaDireccion);
		partes = new ArrayList<Parte>();
		// Crea las partes del barco y avisa a las posiciones que esta en ese lugar.
		int i = 0;
		for (Posicion posicion: posiciones) {
			partes.add(crearParte(i));
			posicion.agregarBarco(this);
			i++;
		}
	}
	
	protected Parte crearParte(int numeroDeParte) {
		return new Parte(numeroDeParte);
	}

	protected void recibirDanio(Posicion posicionDeExplosion) {
		// Si posicionDeExplosion esta entre las posiciones del barco,
		// las daña.
		if (posiciones.contains(posicionDeExplosion)) {
			int indiceDeLaPosicion = posiciones.indexOf(posicionDeExplosion);
			partes.get(indiceDeLaPosicion).recibirDanio();
		}
	}

	public void sacarBarco() {
		// Le avisa a las posiciones que el barco ya no esta.
		for(int i=0; i<posiciones.size(); i++){
			(posiciones.get(i)).quitarBarco(this);
		}
	}
		
	public List<Posicion> getPosicionesSanas() {
		// Recorre todas las posiciones del barco y devuelve las posiciones en
		// que las partes estan sanas.
		ArrayList<Posicion> posicionesSanas = new ArrayList<Posicion>();
		for (int i = 0; i < tamanio; i++) {
			if ((partes.get(i)).estaSana()) {
				posicionesSanas.add(posiciones.get(i));
			}
		}
		return(posicionesSanas);
	}
	
	public List<Posicion> getPosicionesRotas (){
		// Recorre todas las posiciones del barco y devuelve las posiciones en
		// que las partes estan rotas.
		List<Posicion> posicionesRotas = new ArrayList<Posicion>();
		for(int i = 0; i < tamanio; i++) {
			if ((partes.get(i)).estaRota()) {
				posicionesRotas.add(posiciones.get(i));
			}
		}
		return posicionesRotas;
	}
	
	public List<Posicion> getPosiciones() {
		return posiciones;
	}
	
	public boolean estaDestruido() {
		// Recorre todas las partes del barco, si alguna no esta rota, todavia el barco no esta destruido.
		boolean destruido = true;
		for (Parte parte: partes) {
			if (!parte.estaRota()) {
				destruido = false;
			}
		}
		return destruido;
	}
	
	public void mover(Tablero tablero) {
		posiciones = timon.mover(tablero, this);
	}

	public Direccion getDireccion() {
		return timon.getDireccion();
	}
	
	public abstract void recibirDanioDisparo (Posicion posicionDeExplosion);
	public abstract void recibirDanioPuntualConRetardo (Posicion posicionDeExplosion);
	public abstract void recibirDanioDobleConRetardo (Posicion posicionDeExplosion);
	public abstract void recibirDanioTripleConRetardo (Posicion posicionDeExplosion);
	public abstract void recibirDanioMinaDeContacto (Posicion posicionDeExplosion);

	public List<Parte> getPartesRotas() {
		// Recorre todas las partes del barco y devuelve las posiciones en
		// que las partes estan rotas.
		List<Parte> partesRotas = new ArrayList<Parte>();
		for(int i = 0; i < tamanio; i++) {
			if ((partes.get(i)).estaRota()) {
				partesRotas.add(partes.get(i));
			}
		}
		return partesRotas;		
	}

	public List<Parte> getPartes() {
		return partes;
	}

	public void setPartes(ArrayList<Parte> nuevasPartes) {
		partes = nuevasPartes;		
	}
}